using System;
using System.Web;
using System.ComponentModel;
using System.Web.Services;
using System.Web.Security;
using System.Web.Services.Protocols;
using System.Configuration;
using System.Data;
using System.Data.SqlClient;
using Microsoft.ApplicationBlocks.Data;

namespace HSH
{

    [WebService(Namespace = "http://tempuri.org/")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    public class AuthService : System.Web.Services.WebService
    {
        public AuthService()
        {
            InitializeComponent();
        }

        internal System.Data.SqlClient.SqlConnection dbConn;
		internal DSUsersAuthorizationsTableAdapters.UsersAuthorizationsTableAdapter daUserAuthorizations;
        private IContainer components = null;

        private void InitializeComponent()
        {
            
            AppSettingsReader configurationAppSettings = new AppSettingsReader();
            this.dbConn = new System.Data.SqlClient.SqlConnection();
            this.dbConn.ConnectionString = Convert.ToString(configurationAppSettings.GetValue("dbConn.ConnectionString",typeof(string)));

			this.daUserAuthorizations = new DSUsersAuthorizationsTableAdapters.UsersAuthorizationsTableAdapter();
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing && components != null)
            {
                components.Dispose();
            }
            base.Dispose(disposing);		
        }

        [WebMethod()]
        public string GetAuthorizationTicket(string userName, string password)
        {
            //try to authenticate the user
            string userID = null;
			try
			{
				userID = SqlHelper.ExecuteScalar(dbConn, "AuthenticateUser", userName, password).ToString();
			}
			catch (Exception ex)
			{
				int i = 1;
			}
            finally
            {
                dbConn.Close();
            }

            if (userID == null)
            {
                //The user name and password combination is not valid.
                return null;
            }

            //create the ticket
            FormsAuthenticationTicket ticket = new FormsAuthenticationTicket(userID, false, 2);
            string encryptedTicket = FormsAuthentication.Encrypt(ticket);

            //get the ticket timeout in minutes
            AppSettingsReader configurationAppSettings = new AppSettingsReader();
            int timeout = Convert.ToInt32(configurationAppSettings.GetValue("AuthenticationTicket.Timeout", typeof(int)));

            //cache the ticket
            //Context.Items.Add(encryptedTicket, userID);//, null, DateTime.Now.AddMinutes(timeout), System.Web.Caching.Cache.NoSlidingExpiration);
            Context.Cache.Insert(encryptedTicket, userID, null, DateTime.Now.AddMinutes(timeout), TimeSpan.Zero);

            return encryptedTicket;

        }

        [WebMethod()]
        public UserInformation GetUserInfo(string ticket)
        {
            if (IsTicketValid(ticket, false)==false) return null;

            int userID = Convert.ToInt32(FormsAuthentication.Decrypt(ticket).Name);

            DataSet ds;
            try
            {
                ds = SqlHelper.ExecuteDataset(dbConn, "GetUserInfo", userID);
            }
            finally
            {
                dbConn.Close();
            }

            UserInformation userInfo  = new UserInformation();
            userInfo.UserID = userID;
            userInfo.UserName = Convert.ToString(ds.Tables[0].Rows[0]["UserName"]);
            userInfo.UserFullName = Convert.ToString(ds.Tables[0].Rows[0]["UserFullName"]);
            userInfo.UserEmail = Convert.ToString(ds.Tables[0].Rows[0]["UserEmail"]);
            userInfo.IsAdministrator = Convert.ToBoolean(ds.Tables[0].Rows[0]["IsAdministrator"]);
            userInfo.IsAccountLocked = Convert.ToBoolean(ds.Tables[0].Rows[0]["IsAccountLocked"]);
            userInfo.MustChangePassword = Convert.ToBoolean(ds.Tables[0].Rows[0]["MustChangePassword"]);

            return userInfo;
        }

        [WebMethod()]
        public int InsertUser(string ticket, UserInformation userInfo)
        {
            if (IsTicketValid(ticket, true)==false)
                return -1;

            try
            {
                Object userID;
                userID = SqlHelper.ExecuteScalar(dbConn, "InsertUser", userInfo.UserName,
                    userInfo.UserPassword, userInfo.UserFullName, userInfo.UserEmail, 
                    userInfo.IsAdministrator, userInfo.IsAccountLocked, userInfo.MustChangePassword);

                if (userID ==null)
                    return -1;
                else
                    // Note: @@identity return type is decimal--need to Convert to int!
                    return Convert.ToInt32(userID.ToString());
            }
            catch (SqlException ex)
            {
                if (ex.Number == 2627) 
                    // SQL Server has detected a unique key constraint violation on
                    // the UserName column.  Return the flag value for this case.
                    return 0;
                else
                    throw ex;
            }
            finally
            {
                dbConn.Close();
            }
        }

        [WebMethod()]
        public UserInformation UpdateUser(string ticket, UserInformation userInfo)
        {
            if (IsTicketValid(ticket, true)== false) return null;

            int result;
            try
            {
                result = SqlHelper.ExecuteNonQuery(dbConn, "UpdateUser", userInfo.UserName, userInfo.UserPassword, userInfo.UserFullName, userInfo.UserEmail, userInfo.IsAdministrator, userInfo.IsAccountLocked, userInfo.MustChangePassword, userInfo.UserID);
            }
            finally
            {
                dbConn.Close();
            }
            

            if (result == 1)
                return userInfo;
            else
                return null;
        }

        [WebMethod()]
        public UserInformation ChangePassword(string ticket, UserInformation userInfo)
        {
            if (IsTicketValid(ticket, false)==false) return null;

            int userID = Convert.ToInt32(FormsAuthentication.Decrypt(ticket).Name);

            int result;
            
            try
            {
                result = SqlHelper.ExecuteNonQuery(dbConn, "ChangePassword", userInfo.UserPassword, userID);
            }
            finally
            {
                dbConn.Close();
            }

            if (result == 1)
                return userInfo;
            else
                return null;
        }

        private bool IsTicketValid(string ticket, bool IsAdminCall)
        {
            //return true;

            if (ticket == null || Context.Cache[ticket]== null)
            {
                //not authenticated
                return false;
            }
            else
            {
                //check the user authorization
                int userID = Convert.ToInt32(FormsAuthentication.Decrypt(ticket).Name);

                DataSet ds;
                try
                {
                    ds = SqlHelper.ExecuteDataset(dbConn, "GetUserInfo", userID);
                }
                finally
                {
                    dbConn.Close();
                }

                UserInformation userInfo = new UserInformation();
                userInfo.IsAdministrator = Convert.ToBoolean(ds.Tables[0].Rows[0]["IsAdministrator"]);
                userInfo.IsAccountLocked = Convert.ToBoolean(ds.Tables[0].Rows[0]["IsAccountLocked"]);
                
                if (userInfo.IsAccountLocked)
                {
                    return false;
                }
                else
                {
                    //check admin status (for admin required calls)
                    if (IsAdminCall && userInfo.IsAdministrator==false) 
                        return false;
                    
                    return true;
                }
            }
        }

		[WebMethod(Description = "Returns a DataSet containing all users authorizations for managment. contain the UsersAuthorizations view.")]
		public DSUsersAuthorizations GetUsersAuth(string ticket)
		{
			if (!IsTicketValid(ticket, false))
				return null;

			DSUsersAuthorizations ds = new DSUsersAuthorizations();
			daUserAuthorizations.Fill(ds.UsersAuthorizations);

			return ds;
		}

		[WebMethod()]
		public object RemoveUserAuthorization(string ticket, int UserId, int KenId, int AuthLevelId)
		{
			if (IsTicketValid(ticket, false) == false) return null;

			int ManagerUserID = Convert.ToInt32(FormsAuthentication.Decrypt(ticket).Name);

			int result;

			try
			{
				result = SqlHelper.ExecuteNonQuery(dbConn, "RemoveUserAuthorization", UserId, KenId, AuthLevelId, ManagerUserID);
			}
			finally
			{
				dbConn.Close();
			}

			if (result == 1)
				return (object)true;
			else
				return (object)false;
		}

		[WebMethod()]
		public int InsertUserAuthorization(string ticket, int UserId, int KenId, int AuthLevelId)
		{
			if (IsTicketValid(ticket, true) == false)
				return -1;

			int ManagerUserID = Convert.ToInt32(FormsAuthentication.Decrypt(ticket).Name);

			try
			{
				Object retVal;
				retVal = SqlHelper.ExecuteScalar(dbConn, "InsertUserAuthorization", UserId, KenId, AuthLevelId, ManagerUserID);

				if (retVal == null)
					return -1;
				
				return Convert.ToInt32(retVal);	//1 good, 0 - not good
			}
			catch (SqlException ex)
			{
				if (ex.Number == 2627)
					// SQL Server has detected a unique key constraint violation on
					// the UserName column.  Return the flag value for this case.
					return 0;
				else
					throw ex;
			}
			finally
			{
				dbConn.Close();
			}
		}

    }
}

